package com.yuxi.shuzu;

import java.util.Arrays;

/*
   Arrays工具类:
        特点：
            1. 工具类一般被final修饰,没有子类                                     面向对象再讲解
            2. 工具类中只有一个私有的无参构造方法  private Arrays() {}              面向对象再讲解
            3. 工具类中所有对外公开的方法都是static修饰的, 调用是都是Arrays直接调用   面向对象再讲解

        学习工具类的好处：
            1. 数组工具类中提供了很多操作数组的方法、功能, 程序员可以直接使用。
 */
/*
   模拟数组工具类：Arrays
 */
public final class Demo4 {
    private Demo4(){}
    public static void main(String[] args) {
        // 1. 定义数组
        int[] arr = {1,2,3,4,5};
        System.out.println(Arrays.toString(arr)); // [1, 2, 3, 4, 5]
        System.out.println(Demo4.myToString(arr)); // [1, 2, 3, 4, 5]

        int[] arr1 = {1,2,3};
        int[] arr2 = {1,2,3,4};
        boolean equals = Arrays.equals(arr1, arr2);
        System.out.println("equals = " + equals);
        int[] arr3 = {1,2,3};
        int[] arr4 = {3,2,1};
        boolean b = Demo4.myEquals(arr3, arr4);
        System.out.println("b = " + b);
        int[] arr5 = {3,5,4,2,1};
        // Arrays.sort(arr5);
        // System.out.println(Demo4.myToString(arr5));// [1, 2, 3, 4, 5]
        Demo4.mySort(arr5);
        System.out.println(Demo4.myToString(arr5));// [1, 2, 3, 4, 5]
        // int index = Arrays.binarySearch(arr5, 5);
        int index = Demo4.myBinarySearch(arr5, 7);
        System.out.println("index = " + index);// index = -6

        int[] arr6 = new int[10];
        Arrays.fill(arr6,7);
        System.out.println(Demo4.myToString(arr6)); // [7, 7, 7, 7, 7, 7, 7, 7, 7, 7]

        int[] arr7 = {0,1,2,3,4,5,6,7,8,9};
        // int[] newArr = Arrays.copyOf(arr7, -5);
        int[] newArr = Demo4.myCopyOf(arr7, 5);
        System.out.println(Demo4.myToString(newArr));//[0, 1, 2, 3, 4]

       /* int[] newArr2 = Arrays.copyOfRange(arr7, 3, 8);// 拷贝 arr7 ： [3,8)
        System.out.println(Demo4.myToString(newArr2)); // [3, 4, 5, 6, 7]*/

        int[] newArr3 = Demo4.myCopyOfRange(arr7, 3, 20);
        System.out.println(Demo4.myToString(newArr3)); // [3, 4, 5, 6, 7]

    }

    // 自定义数组拷贝,不从0索引开始
    public static int[] myCopyOfRange(int[] arr , int from , int to){
        // 1. 数据校验arr
        if(arr == null || arr.length == 0){
            System.err.println("数组不能为null,也不能为空数组");
            System.exit(0);
        }
        // 2. 数据校验长度
        if(from > to){
            System.err.println("拷贝的元素个数不能小于0个");
            System.exit(0);
        }
        if(from < 0 ){
            System.err.println("开始拷贝元素的索引不能小于0");
            System.exit(0);
        }
        // 3. 判断
        int newLength = to - from;
        int[] newArr = new int[newLength];
        if(newLength <= arr.length - from){ // 新的数组短
            for (int i = 0; i < newArr.length; i++) {
                newArr[i] = arr[i + from];
            }
        }
        else{ // 老数组短
            for (int i = 0; i < arr.length - from; i++) {
                newArr[i] = arr[i + from];
            }
        }
        return newArr;
    }
    // 自定义数组拷贝方法
    public static int[] myCopyOf(int[] arr , int newLength){
        // 1. 数据校验arr
        if(arr == null || arr.length == 0){
            System.err.println("数组不能为null,也不能为空数组");
            System.exit(0);
        }
        // 2. 数据校验长度
        if(newLength < 0 ){
            System.err.println("拷贝的元素的个数不能为负数");
            System.exit(0);
        }
        // 3. 根据newLength创建新数组
        int[] newArr = new int[newLength];
        if(newLength <= arr.length){ // 新数组短
            // 4. 遍历数组arr，元素平移
            for (int i = 0; i < newArr.length; i++) {
                newArr[i] = arr[i];
            }
        }
        else { // 老数组短
            for (int i = 0; i < arr.length; i++) {
                newArr[i] = arr[i];
            }
        }

        // 5. 返回新数组
        return newArr;
    }


    // 自定义一个二分查找算法
    public static int myBinarySearch(int[] arr , int key){
        // 1. 数据校验
        if(arr == null || arr.length == 0){
            System.out.println("数组不能为null,也不能为空数组");
            System.exit(0);
        }
        // 2. 数组不为null并且有元素
        int start = 0 , end = arr.length - 1 , mid;

        while (start <= end) {
            mid = (start + end) >>> 1;
            // 判断
            if(key > arr[mid]){
                start = mid + 1;
            }
            else if(key < arr[mid]){
                end = mid - 1;
            }
            else{
                return mid;
            }
        }
        return -(start+1);
    }

    // 自定义一个sort()
    public static void mySort(int[] arr){
        if(arr == null || arr.length == 0 ){
            System.out.println("数组不能为null,也不能为空数组");
            return;
        }
        // 程序走到此处,说明arr不为null并且里面有元素
        for (int i = 0; i < arr.length - 1; i++) { // 控制排序的轮数: [0,3]
            // 假设数组有序
            boolean flag = true;
            for (int j = 0; j < arr.length - 1 - i; j++) { // 控制每一轮比较的次数
                if (arr[j] > arr[j + 1]) {
                    flag = false;
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            // 判断
            if(flag){
                break;
            }
        }
    }


    // 自定义equals方法
    public static boolean myEquals(int[] arr1 , int[] arr2){
        // 1. 比较如果两个数组的内存地址值相同直接返回true
        if( arr1 == arr2 ){
            return true;
        }
        // 2. 程序走到此处，说明arr1和arr2不是同一个数组，比较是否为null
        if(arr1 == null || arr2 == null){
            return  false;
        }
        // 3. 程序走到此处，说明arr1和arr2不是同一个数组也不是null,在看长度是否相同
        if(arr1.length != arr2.length){
            return false;
        }
        // 4. 程序走到此处，说明arr1和arr2不是同一个数组也不是null,而且长度相同,在看 每一个索引位置的元素对应是否都相等
        for (int i = 0; i < arr1.length; i++) {
            if(arr1[i] != arr2[i]){
                return  false;
            }
        }
        // 5. 程序走到此处,说明arr1和arr2不是同一个数组也不是null,而且长度相同,每一个索引位置的元素对应都相等
        return true;
    }


    public static String myToString(int[] arr){
        String str = "[";
        for (int i = 0; i < arr.length; i++) {
            if(i == arr.length - 1){
                str = str + arr[i];
            }
            else{
                str = str + arr[i] + ", ";
            }
        }
        str = str + "]";
        return  str;
    }
}
